﻿namespace MicroCloud.Utils
{
    /// <summary>
    /// XML辅助扩展操作
    /// </summary>
    public static class XmlExtensions
    {
        #region "方法"
        // XmlDocument
        #region "根据XML架构验证XML字符串合法性"
        /// <summary>
        /// 根据XML架构验证XML字符串合法性
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xsdTextReader">XSD架构文本读取器</param>
        /// <param name="message">验证消息</param>
        /// <param name="throwError">是否抛出异常</param>
        /// <returns></returns>
        public static bool Validate(this XmlDocument xmlDocument, TextReader xsdTextReader, out string message, bool throwError = false)
        {
            Check.NotNull(xmlDocument, nameof(xmlDocument));
            Check.NotNull(xsdTextReader, nameof(xsdTextReader));

            XmlReader xsdReader = XmlReader.Create(xsdTextReader);

            return Validate(xmlDocument, xsdReader, out message, throwError);
        }
        #endregion
        #region "根据XML架构验证XML字符串合法性"
        /// <summary>
        /// 根据XML架构验证XML字符串合法性
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xsdStream">XSD架构流</param>
        /// <param name="message">验证消息</param>
        /// <param name="throwError">是否抛出异常</param>
        /// <returns></returns>
        public static bool Validate(this XmlDocument xmlDocument, Stream xsdStream, out string message, bool throwError = false)
        {
            Check.NotNull(xmlDocument, nameof(xmlDocument));
            Check.NotNull(xsdStream, nameof(xsdStream));

            XmlReader xsdReader = XmlReader.Create(xsdStream);

            return Validate(xmlDocument, xsdReader, out message, throwError);
        }
        #endregion
        #region "根据XML架构验证XML字符串合法性"
        /// <summary>
        /// 根据XML架构验证XML字符串合法性
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xsdReader">XSD架构读取器</param>
        /// <param name="message">验证消息</param>
        /// <param name="throwError">是否抛出异常</param>
        /// <returns></returns>
        public static bool Validate(this XmlDocument xmlDocument, XmlReader xsdReader, out string message, bool throwError = false)
        {
            message = "";
            var msgString = "";
            var isError = false;
            Check.NotNull(xmlDocument, nameof(xmlDocument));
            Check.NotNull(xsdReader, nameof(xsdReader));

            XmlSchemaSet xmlSchemaSet = new();
            StringReader stringReader = new(xmlDocument.OuterXml);

            XmlReader xmlReader = null;
            //xmlSchemaSet.Add(null, @"MySchema.xsd");
            //xmlSchemaSet.Add("", XmlReader.Create("path")); 
            try
            {
                xmlSchemaSet.Add("", xsdReader);

                XmlReaderSettings settings = new();
                //settings.ValidationEventHandler += new ValidationEventHandler(ValidationEventCallBack);
                settings.ValidationEventHandler += delegate (object sender, ValidationEventArgs e)
                {
                    try
                    {
                        if (e.Severity == XmlSeverityType.Warning)//区分是警告还是错误 
                        {
                            //Console.WriteLine("验证成功!警告：" + e.Message);
                            msgString += "Warning：" + e.Message;
                        }
                        else
                        {
                            // Console.WriteLine("验证失败");
                            msgString += "Error：" + e.Message;
                            isError = true;
                        }
                    }
                    catch (System.Exception ex)
                    {
                        msgString += ex.Message;
                    }
                };
                settings.ValidationType = ValidationType.Schema;
                settings.Schemas = xmlSchemaSet;

                xmlReader = XmlReader.Create(stringReader, settings);
                while (xmlReader.Read()) { }

                //if (!isError)
                //{
                //    //Console.WriteLine("验证成功!");
                //}
                //else
                //{
                //    //Console.WriteLine("验证失败！原因可能是：" + ErrString);
                //}
            }
            catch (XmlException xmlEx)
            {
                msgString += xmlEx.Message;
                //Console.WriteLine(xmlEx.Message);
            }
            finally
            {
                xmlReader?.Close();
            }
            message = msgString;
            if (throwError && isError)
            {
                throw new Exception(message);
            }
            return isError;
        }
        #endregion

        #region "创建一个XML文档，如果XML不为NULL，则向现有文档中追加节点"
        /// <summary>
        /// 创建一个XML文档，如果XML不为NULL，则向现有文档中追加节点
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="rootNodeName">XML文档根节点名称(须指定一个根节点名称)</param>
        /// <param name="clear">是否清除现有项</param>
        /// <param name="version">XML文档版本号(必须为:"1.0")</param>
        /// <param name="encoding">XML文档编码方式</param>
        /// <param name="standalone">该值必须是"yes"或"no",如果为null,Save方法不在XML声明上写出独立属性</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument Create(this XmlDocument xmlDocument, string rootNodeName, bool clear = false, string version = "1.0", string encoding = "UTF-8", string standalone = "yes")
        {
            if (xmlDocument == null)
            {
                xmlDocument = new XmlDocument();
                XmlDeclaration xmlDeclaration = xmlDocument.CreateXmlDeclaration(version, encoding, standalone);
                xmlDocument.AppendChild(xmlDeclaration);
            }
            else if (clear)
            {
                xmlDocument.RemoveAll();
            }
            if (!rootNodeName.IsMissing())
            {
                XmlNode root = xmlDocument.CreateElement(rootNodeName);
                xmlDocument.AppendChild(root);
            }

            return xmlDocument;
        }
        #endregion

        #region "选择匹配XPath表达式的第一个节点XmlNode"
        /// <summary>
        /// 选择匹配XPath表达式的第一个节点XmlNode
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名")</param>
        /// <returns>返回XmlNode</returns>
        public static XmlNode GetNode(this XmlDocument xmlDocument, string xpath)
        {
            //XmlNode xmlNode = xmlDocument.SelectSingleNode(xpath);
            XmlNode xmlNode = xmlDocument.DocumentElement.SelectSingleNode(xpath);
            return xmlNode;
        }
        #endregion

        #region "依据匹配XPath表达式更新节点"
        /// <summary>
        /// 依据匹配XPath表达式更新节点
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument UpdateNode(this XmlDocument xmlDocument, string xpath, string xmlNodeName, string innerText, Dictionary<string, string> attributes)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNode xmlNode = xmlDocument.GetNode(xpath);
            if (xmlNode != null)
            {
                //存不存在此节点都创建
                XmlElement subElement = xmlDocument.CreateElement(xmlNodeName);
                if (!innerText.IsMissing())
                {
                    subElement.InnerText = innerText;
                }

                //如果属性和值参数都不为空则在此新节点上新增属性
                foreach (var attribute in attributes)
                {
                    if (!attribute.Key.IsMissing() && !attribute.Value.IsMissing())
                    {
                        XmlAttribute xmlAttribute = xmlDocument.CreateAttribute(attribute.Key);
                        xmlAttribute.Value = attribute.Value;
                        subElement.Attributes.Append(xmlAttribute);
                    }
                }

                xmlDocument.ReplaceChild(subElement, xmlNode);
            }

            return xmlDocument;
        }
        #endregion
        #region "依据匹配XPath表达式移除节点"
        /// <summary>
        /// 依据匹配XPath表达式移除节点
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument RemoveNode(this XmlDocument xmlDocument, string xpath)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNode xmlNode = xmlDocument.GetNode(xpath);
            xmlNode?.RemoveChild(xmlNode);

            return xmlDocument;
        }
        #endregion

        #region "依据匹配XPath表达式的第一个节点来创建它的子节点"
        /// <summary>
        /// 依据匹配XPath表达式的第一个节点来创建它的子节点
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument CreateChildNode(this XmlDocument xmlDocument, string xpath, string xmlNodeName, string innerText, Dictionary<string, string> attributes)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNode xmlNode = xmlDocument.GetNode(xpath);
            xmlNode?.CreateChildNode(xmlNodeName, innerText, attributes);

            return xmlDocument;
        }
        #endregion
        #region "依据匹配XPath表达式的第一个节点来更新它的子节点"
        /// <summary>
        /// 依据匹配XPath表达式的第一个节点来更新它的子节点
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument UpdateChildNode(this XmlDocument xmlDocument, string xpath, string xmlNodeName, string innerText, Dictionary<string, string> attributes)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNode xmlNode = xmlDocument.GetNode(xpath);
            xmlNode?.UpdateChildNode(xmlNodeName, innerText, attributes);

            return xmlDocument;
        }
        #endregion
        #region "依据匹配XPath表达式的第一个节点来创建或更新它的子节点"
        /// <summary>
        /// 依据匹配XPath表达式的第一个节点来创建或更新它的子节点
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument CreateOrUpdateChildNode(this XmlDocument xmlDocument, string xpath, string xmlNodeName, string innerText, Dictionary<string, string> attributes)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNode xmlNode = xmlDocument.GetNode(xpath);
            if (xmlNode != null)
            {
                xmlNode.CreateOrUpdateChildNode(xmlNodeName, innerText, attributes);
            }

            return xmlDocument;
        }
        #endregion
        #region "依据匹配XPath表达式的第一个节点来移除它的子节点"
        /// <summary>
        /// 依据匹配XPath表达式的第一个节点来移除它的子节点
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument RemoveChildNode(this XmlDocument xmlDocument, string xpath, string xmlNodeName)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNode xmlNode = xmlDocument.GetNode(xpath);
            xmlNode?.RemoveChildNode(xmlNodeName);

            return xmlDocument;
        }
        #endregion

        #region "选择匹配XPath表达式的节点列表XmlNode集合"
        /// <summary>
        /// 选择匹配XPath表达式的节点列表XmlNode集合
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名")</param>
        /// <returns>返回的XmlNode集合</returns>
        public static XmlNodeList GetNodeList(this XmlDocument xmlDocument, string xpath)
        {
            XmlNodeList xmlNodeList = xmlDocument.DocumentElement.SelectNodes(xpath);
            return xmlNodeList;
        }
        #endregion

        #region "依据匹配XPath表达式的所有节点来创建它的子节点"
        /// <summary>
        /// 依据匹配XPath表达式的所有节点来创建它的子节点
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument CreateChildNodeList(this XmlDocument xmlDocument, string xpath, string xmlNodeName, string innerText, Dictionary<string, string> attributes)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNodeList xmlNodeList = xmlDocument.GetNodeList(xpath);
            xmlNodeList?.CreateChildNode(xmlNodeName, innerText, attributes);

            return xmlDocument;
        }
        #endregion
        #region "依据匹配XPath表达式的所有节点来更新它的子节点"
        /// <summary>
        /// 依据匹配XPath表达式的所有节点来更新它的子节点
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument UpdateChildNodeList(this XmlDocument xmlDocument, string xpath, string xmlNodeName, string innerText, Dictionary<string, string> attributes)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNodeList xmlNodeList = xmlDocument.GetNodeList(xpath);
            xmlNodeList?.UpdateChildNode(xmlNodeName, innerText, attributes);

            return xmlDocument;
        }
        #endregion
        #region "依据匹配XPath表达式的所有节点来创建或更新它的子节点"
        /// <summary>
        /// 依据匹配XPath表达式的所有节点来创建或更新它的子节点
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument CreateOrUpdateChildNodeList(this XmlDocument xmlDocument, string xpath, string xmlNodeName, string innerText, Dictionary<string, string> attributes)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNodeList xmlNodeList = xmlDocument.GetNodeList(xpath);
            xmlNodeList?.CreateOrUpdateChildNode(xmlNodeName, innerText, attributes);

            return xmlDocument;
        }
        #endregion
        #region "依据匹配XPath表达式的所有节点来移除它的子节点"
        /// <summary>
        /// 依据匹配XPath表达式的所有节点来移除它的子节点
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument RemoveChildNodeList(this XmlDocument xmlDocument, string xpath, string xmlNodeName)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNodeList xmlNodeList = xmlDocument.GetNodeList(xpath);
            xmlNodeList?.RemoveChildNode(xmlNodeName);

            return xmlDocument;
        }
        #endregion

        #region "依据匹配XPath表达式的第一个节点来设置属性"
        /// <summary>
        /// 依据匹配XPath表达式的第一个节点来设置属性
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <param name="createIfNotExisted">不存在时创建属性</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument SetAttribute(this XmlDocument xmlDocument, string xpath, Dictionary<string, string> attributes, bool createIfNotExisted = true)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNode xmlNode = xmlDocument.GetNode(xpath);
            xmlNode?.SetAttribute(attributes, createIfNotExisted);

            return xmlDocument;
        }
        #endregion
        #region "依据匹配XPath表达式的第一个节点来移除属性"
        /// <summary>
        /// 依据匹配XPath表达式的第一个节点来移除属性
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <param name="attributeNames">要删除的xmlAttributeName的属性名称</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument RemoveAttribute(this XmlDocument xmlDocument, string xpath, params string[] attributeNames)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNode xmlNode = xmlDocument.GetNode(xpath);
            xmlNode?.RemoveAttribute(attributeNames);

            return xmlDocument;
        }
        #endregion
        #region "依据匹配XPath表达式的第一个节点来清空属性"
        /// <summary>
        /// 依据匹配XPath表达式的第一个节点来清空属性
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument ClearAttribute(this XmlDocument xmlDocument, string xpath)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNode xmlNode = xmlDocument.GetNode(xpath);
            xmlNode?.ClearAttribute();

            return xmlDocument;
        }
        #endregion

        #region "依据匹配XPath表达式的所有节点来设置属性"
        /// <summary>
        /// 依据匹配XPath表达式的所有节点来设置属性
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <param name="createIfNotExisted">不存在时创建属性</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument SetAttributes(this XmlDocument xmlDocument, string xpath, Dictionary<string, string> attributes, bool createIfNotExisted = true)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNodeList xmlNodeList = xmlDocument.GetNodeList(xpath);
            xmlNodeList?.SetAttribute(attributes, createIfNotExisted);

            return xmlDocument;
        }
        #endregion
        #region "依据匹配XPath表达式的所有节点来移除属性"
        /// <summary>
        /// 依据匹配XPath表达式的所有节点来移除属性
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <param name="attributeNames">要删除的xmlAttributeName的属性名称</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument RemoveAttributes(this XmlDocument xmlDocument, string xpath, params string[] attributeNames)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNodeList xmlNodeList = xmlDocument.GetNodeList(xpath);
            xmlNodeList?.RemoveAttribute(attributeNames);

            return xmlDocument;
        }
        #endregion
        #region "依据匹配XPath表达式的所有节点来清空属性"
        /// <summary>
        /// 依据匹配XPath表达式的所有节点来清空属性
        /// </summary>
        /// <param name="xmlDocument">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名)</param>
        /// <returns>处理后的XML文档</returns>
        public static XmlDocument ClearAttributes(this XmlDocument xmlDocument, string xpath)
        {
            if (xmlDocument == null)
            {
                return xmlDocument;
            }

            XmlNodeList xmlNodeList = xmlDocument.GetNodeList(xpath);
            xmlNodeList?.ClearAttribute();

            return xmlDocument;
        }
        #endregion

        // XmlNode
        #region "获取节点文本"
        /// <summary>
        /// 获取节点文本
        /// </summary>
        /// <param name="xmlNode">XML节点</param>
        /// <param name="childNodeName">子节点名称</param>
        /// <returns>文本</returns>
        public static string GetNodeText(this XmlNode xmlNode, string childNodeName)
        {
            return xmlNode.SelectSingleNode(childNodeName).InnerText;
        }
        #endregion
        #region "获取节点指定属性值"
        /// <summary>
        /// 获取节点指定属性值
        /// </summary>
        /// <param name="xmlNode">xml节点</param>
        /// <param name="attributeName">属性名称</param>
        /// <returns>属性值</returns>
        public static string GetAttributeValue(this XmlNode xmlNode, string attributeName)
        {
            if (xmlNode == null || attributeName.IsMissing())
            {
                return null;
            }
            string attributeText = null;
            XmlAttribute xmlAttribute = xmlNode.Attributes[attributeName];
            if (xmlAttribute != null)
            {
                //attributeText = xmlAttribute.InnerText;
                attributeText = xmlAttribute.Value;
                return attributeText;
            }
            xmlAttribute = xmlNode.Attributes[attributeName.ToLower()];
            if (xmlAttribute != null)
            {
                //attributeText = xmlAttribute.InnerText;
                attributeText = xmlAttribute.Value;
                return attributeText;
            }
            xmlAttribute = xmlNode.Attributes[attributeName.ToUpper()];
            if (xmlAttribute != null)
            {
                //attributeText = xmlAttribute.InnerText;
                attributeText = xmlAttribute.Value;
                return attributeText;
            }
            foreach (XmlAttribute attribute in xmlNode.Attributes)
            {
                if (attribute.Name.ToLower() == attributeName.ToLower())
                {
                    //attributeText = attribute.InnerText;
                    attributeText = attribute.Value;
                    return attributeText;
                }
            }
            //for (int i = 0; i < xmlNode.Attributes.Count; i++)
            //{
            //    xmlAttribute = xmlNode.Attributes[i];
            //    if (xmlAttribute?.Name.ToLower() == attributeName.ToLower())
            //    {
            //        //attributeText = xmlAttribute.InnerText;
            //        attributeText = xmlAttribute.Value;
            //        return attributeText;
            //    }
            //}

            return attributeText;
        }
        #endregion
        #region "设置节点的指定属性值"
        /// <summary>
        /// 设置节点的指定属性值
        /// </summary>
        /// <param name="xmlNode">XML节点</param>
        /// <param name="name">属性名称</param>
        /// <param name="value">属性值</param>
        /// <param name="createIfNotExisted">不存在时创建属性</param>
        /// <returns>处理后的XML节点</returns>
        public static XmlNode SetAttribute(this XmlNode xmlNode, string name, string value, bool createIfNotExisted = true)
        {
            if (xmlNode == null)
            {
                return xmlNode;
            }

            bool existed = false;
            if (!name.IsMissing() && !value.IsMissing())
            {
                //遍历xpath节点中的所有属性
                foreach (XmlAttribute xmlAttribute in xmlNode.Attributes)
                {
                    if (xmlAttribute.Name.ToLower() == name.ToLower())
                    {
                        //节点中存在此属性则更新
                        xmlAttribute.Value = value;
                        existed = true;
                        break;
                    }
                }
                if (!existed && createIfNotExisted)
                {
                    //节点中不存在此属性则创建
                    XmlAttribute xmlAttribute = xmlNode.OwnerDocument.CreateAttribute(name);
                    xmlAttribute.Value = value;
                    xmlNode.Attributes.Append(xmlAttribute);
                }
            }

            //if (xmlNode.Attributes[name] != null)
            //{
            //    xmlNode.Attributes[name].Value = value;
            //}
            //else
            //{
            //    var xmlAttribute = xmlNode.OwnerDocument.CreateAttribute(name);
            //    xmlAttribute.Value = value;
            //    xmlNode.Attributes.Append(xmlAttribute);
            //}
            return xmlNode;
        }
        #endregion
        #region "设置节点的指定属性值"
        /// <summary>
        /// 设置节点的指定属性值
        /// </summary>
        /// <param name="xmlNode">XML节点</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <param name="createIfNotExisted">不存在时创建属性</param>
        /// <returns>处理后的XML节点</returns>
        public static XmlNode SetAttribute(this XmlNode xmlNode, Dictionary<string, string> attributes, bool createIfNotExisted = true)
        {
            foreach (var attribute in attributes)
            {
                xmlNode = xmlNode.SetAttribute(attribute.Key, attribute.Value);
            }

            return xmlNode;
        }
        #endregion
        #region "移除节点的指定属性项"
        /// <summary>
        /// 移除节点的指定属性项
        /// </summary>
        /// <param name="xmlNode">XML节点</param>
        /// <param name="attributeNames">要删除的xmlAttributeName的属性名称</param>
        /// <returns>处理后的XML节点</returns>
        public static XmlNode RemoveAttribute(this XmlNode xmlNode, params string[] attributeNames)
        {
            if (xmlNode == null)
            {
                return xmlNode;
            }

            foreach (var attributeName in attributeNames)
            {
                if (!attributeName.IsMissing())
                {
                    //遍历xpath节点中的所有属性
                    foreach (XmlAttribute xmlAttribute in xmlNode.Attributes)
                    {
                        if (xmlAttribute.Name.ToLower() == attributeName.ToLower())
                        {
                            //删除节点中的属性
                            xmlNode.Attributes.Remove(xmlAttribute);
                            break;
                        }
                    }
                }
            }

            return xmlNode;
        }
        #endregion
        #region "清空节点的所有属性项"
        /// <summary>
        /// 清空节点的所有属性项
        /// </summary>
        /// <param name="xmlNode">XML节点</param>
        /// <returns>处理后的XML节点</returns>
        public static XmlNode ClearAttribute(this XmlNode xmlNode)
        {
            if (xmlNode == null)
            {
                return xmlNode;
            }

            xmlNode.Attributes.RemoveAll();

            return xmlNode;
        }
        #endregion

        #region "创建节点的子节点"
        /// <summary>
        /// 创建节点的子节点
        /// </summary>
        /// <param name="xmlNode">XML节点</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <returns>处理后的XML节点</returns>
        public static XmlNode CreateChildNode(this XmlNode xmlNode, string xmlNodeName, string innerText, Dictionary<string, string> attributes)
        {
            if (xmlNode == null)
            {
                return xmlNode;
            }

            //存不存在此节点都创建
            XmlElement subElement = xmlNode.OwnerDocument.CreateElement(xmlNodeName);
            if (!innerText.IsMissing())
            {
                subElement.InnerText = innerText;
            }

            //如果属性和值参数都不为空则在此新节点上新增属性
            foreach (var attribute in attributes)
            {
                if (!attribute.Key.IsMissing() && !attribute.Value.IsMissing())
                {
                    XmlAttribute xmlAttribute = xmlNode.OwnerDocument.CreateAttribute(attribute.Key);
                    xmlAttribute.Value = attribute.Value;
                    subElement.Attributes.Append(xmlAttribute);
                }
            }
            xmlNode.AppendChild(subElement);

            return xmlNode;
        }
        #endregion
        #region "更新节点的子节点"
        /// <summary>
        /// 更新节点的子节点
        /// </summary>
        /// <param name="xmlNode">XML节点</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <returns>处理后的XML节点</returns>
        public static XmlNode UpdateChildNode(this XmlNode xmlNode, string xmlNodeName, string innerText, Dictionary<string, string> attributes)
        {
            if (xmlNode == null)
            {
                return xmlNode;
            }

            //创建
            XmlElement subElement = xmlNode.OwnerDocument.CreateElement(xmlNodeName);
            if (!innerText.IsMissing())
            {
                subElement.InnerText = innerText;
            }
            //如果属性和值参数都不为空则在此新节点上新增属性
            foreach (var attribute in attributes)
            {
                if (!attribute.Key.IsMissing() && !attribute.Value.IsMissing())
                {
                    XmlAttribute xmlAttribute = xmlNode.OwnerDocument.CreateAttribute(attribute.Key);
                    xmlAttribute.Value = attribute.Value;
                    subElement.Attributes.Append(xmlAttribute);
                }
            }
            foreach (XmlNode oldXmlNode in xmlNode.ChildNodes)
            {
                if (oldXmlNode.Name.ToLower() == xmlNodeName.ToLower())
                {
                    xmlNode.ReplaceChild(subElement, oldXmlNode);
                }
            }

            return xmlNode;
        }
        #endregion
        #region "创建或更新节点的子节点"
        /// <summary>
        /// 创建或更新节点的子节点
        /// </summary>
        /// <param name="xmlNode">XML节点</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <returns>处理后的XML节点</returns>
        public static XmlNode CreateOrUpdateChildNode(this XmlNode xmlNode, string xmlNodeName, string innerText, Dictionary<string, string> attributes)
        {
            if (xmlNode == null)
            {
                return xmlNode;
            }

            bool existed = false;
            //创建
            XmlElement subElement = xmlNode.OwnerDocument.CreateElement(xmlNodeName);
            if (!innerText.IsMissing())
            {
                subElement.InnerText = innerText;
            }
            //如果属性和值参数都不为空则在此新节点上新增属性
            foreach (var attribute in attributes)
            {
                if (!attribute.Key.IsMissing() && !attribute.Value.IsMissing())
                {
                    XmlAttribute xmlAttribute = xmlNode.OwnerDocument.CreateAttribute(attribute.Key);
                    xmlAttribute.Value = attribute.Value;
                    subElement.Attributes.Append(xmlAttribute);
                }
            }
            foreach (XmlNode oldXmlNode in xmlNode.ChildNodes)
            {
                if (oldXmlNode.Name.ToLower() == xmlNodeName.ToLower())
                {
                    xmlNode.ReplaceChild(subElement, oldXmlNode);
                    existed = true;
                }
            }
            if (!existed)
            {
                xmlNode.AppendChild(subElement);
            }

            return xmlNode;
        }
        #endregion
        #region "移除节点的子节点"
        /// <summary>
        /// 移除节点的子节点
        /// </summary>
        /// <param name="xmlNode">XML节点</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <returns>处理后的XML节点</returns>
        public static XmlNode RemoveChildNode(this XmlNode xmlNode, string xmlNodeName)
        {
            if (xmlNode == null)
            {
                return xmlNode;
            }

            foreach (XmlNode oldXmlNode in xmlNode.ChildNodes)
            {
                if (oldXmlNode.Name.ToLower() == xmlNodeName.ToLower())
                {
                    xmlNode.RemoveChild(oldXmlNode);
                }
            }

            return xmlNode;
        }
        #endregion

        // XmlNodeList
        #region "设置节点列表的指定属性值"
        /// <summary>
        /// 设置节点列表的指定属性值
        /// </summary>
        /// <param name="xmlNodeList">XML节点列表</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <param name="createIfNotExisted">不存在时创建属性</param>
        /// <returns>处理后的XML节点列表</returns>
        public static XmlNodeList SetAttribute(this XmlNodeList xmlNodeList, Dictionary<string, string> attributes, bool createIfNotExisted = true)
        {
            if (xmlNodeList == null)
            {
                return xmlNodeList;
            }

            foreach (XmlNode xmlNode in xmlNodeList)
            {
                xmlNode.SetAttribute(attributes, createIfNotExisted);
            }

            return xmlNodeList;
        }
        #endregion
        #region "移除节点列表的指定属性项"
        /// <summary>
        /// 移除节点列表的指定属性项
        /// </summary>
        /// <param name="xmlNodeList">XML节点列表</param>
        /// <param name="attributeNames">要删除的xmlAttributeName的属性名称</param>
        /// <returns>处理后的XML节点列表</returns>
        public static XmlNodeList RemoveAttribute(this XmlNodeList xmlNodeList, params string[] attributeNames)
        {
            if (xmlNodeList == null)
            {
                return xmlNodeList;
            }

            foreach (XmlNode xmlNode in xmlNodeList)
            {
                xmlNode.RemoveAttribute(attributeNames);
            }

            return xmlNodeList;
        }
        #endregion
        #region "清空节点列表的所有属性项"
        /// <summary>
        /// 清空节点列表的所有属性项
        /// </summary>
        /// <param name="xmlNodeList">XML节点列表</param>
        /// <returns>处理后的XML节点列表</returns>
        public static XmlNodeList ClearAttribute(this XmlNodeList xmlNodeList)
        {
            if (xmlNodeList == null)
            {
                return xmlNodeList;
            }

            foreach (XmlNode xmlNode in xmlNodeList)
            {
                xmlNode.ClearAttribute();
            }

            return xmlNodeList;
        }
        #endregion

        #region "创建节点列表的子节点"
        /// <summary>
        /// 创建节点列表的子节点
        /// </summary>
        /// <param name="xmlNodeList">XML节点列表</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <returns>处理后的XML节点列表</returns>
        public static XmlNodeList CreateChildNode(this XmlNodeList xmlNodeList, string xmlNodeName, string innerText, Dictionary<string, string> attributes)
        {
            if (xmlNodeList == null)
            {
                return xmlNodeList;
            }

            foreach (XmlNode xmlNode in xmlNodeList)
            {
                xmlNode.CreateChildNode(xmlNodeName, innerText, attributes);
            }

            return xmlNodeList;
        }
        #endregion
        #region "更新节点列表的子节点"
        /// <summary>
        /// 更新节点列表的子节点
        /// </summary>
        /// <param name="xmlNodeList">XML节点列表</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <returns>处理后的XML节点列表</returns>
        public static XmlNodeList UpdateChildNode(this XmlNodeList xmlNodeList, string xmlNodeName, string innerText, Dictionary<string, string> attributes)
        {
            if (xmlNodeList == null)
            {
                return xmlNodeList;
            }

            foreach (XmlNode xmlNode in xmlNodeList)
            {
                xmlNode.UpdateChildNode(xmlNodeName, innerText, attributes);
            }

            return xmlNodeList;
        }
        #endregion
        #region "创建或更新节点列表的子节点"
        /// <summary>
        /// 创建或更新节点列表的子节点
        /// </summary>
        /// <param name="xmlNodeList">XML节点列表</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="attributes">要设置的节点属性信息</param>
        /// <returns>处理后的XML节点列表</returns>
        public static XmlNodeList CreateOrUpdateChildNode(this XmlNodeList xmlNodeList, string xmlNodeName, string innerText, Dictionary<string, string> attributes)
        {
            if (xmlNodeList == null)
            {
                return xmlNodeList;
            }

            foreach (XmlNode xmlNode in xmlNodeList)
            {
                xmlNode.CreateOrUpdateChildNode(xmlNodeName, innerText, attributes);
            }

            return xmlNodeList;
        }
        #endregion
        #region "移除节点列表的子节点"
        /// <summary>
        /// 移除节点列表的子节点
        /// </summary>
        /// <param name="xmlNodeList">XML节点列表</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <returns>处理后的XML节点列表</returns>
        public static XmlNodeList RemoveChildNode(this XmlNodeList xmlNodeList, string xmlNodeName)
        {
            if (xmlNodeList == null)
            {
                return xmlNodeList;
            }

            foreach (XmlNode xmlNode in xmlNodeList)
            {
                xmlNode.RemoveChildNode(xmlNodeName);
            }

            return xmlNodeList;
        }
        #endregion

        // XmlElement
        #region "设置元素的指定属性值"
        /// <summary>
        /// 设置元素的指定属性值
        /// </summary>
        /// <param name="xmlElement">XML元素</param>
        /// <param name="name">属性名称</param>
        /// <param name="value">属性值</param>
        /// <returns>处理后的XML元素</returns>
        public static XmlElement SetAttributeValue(this XmlElement xmlElement, string name, string value)
        {
            xmlElement.SetAttribute(name, value);
            return xmlElement;
        }
        #endregion

        #endregion

    }

}
